<script setup lang="ts">
// Define props for the component
interface Props {
  id?: string;
  multiple?: boolean;
  disabled?: boolean;
  value?: any | any[];
}

const props = withDefaults(defineProps<Props>(), {
  id: undefined,
  multiple: false,
  disabled: false,
  value: undefined,
});

// Define emits for the component
const emit = defineEmits<{
  (e: 'update:value', value: any | any[]): void;
  (e: 'change', value: any | any[]): void;
  (e: 'connected'): void;
}>();

// Reference to the native element
const listboxRef = ref<HTMLElement | null>(null);

// Watch for changes in the selected values
watch(
  () => props.value,
  (newValue) => {
    if (!listboxRef.value) return;

    // Update the selected state of options based on the value prop
    updateSelectedOptions(newValue);
  },
  { deep: true },
);

// Watch for changes in the multiple prop
watch(
  () => props.multiple,
  (newValue) => {
    if (!listboxRef.value) return;

    // Update the multiple attribute on the native element
    (listboxRef.value as any).multiple = newValue;
  },
  { immediate: true },
);

// Initialize the component after mounting
onMounted(() => {
  if (!listboxRef.value) return;

  // Initial setup of options
  nextTick(() => {
    updateSelectedOptions(props.value);
  });

  // Add event listener for option selection changes
  listboxRef.value.addEventListener('click', handleOptionClick);

  // Add event listener for connected event
  listboxRef.value.addEventListener('connected', () => {
    emit('connected');
  });
});

// Update selected options based on the value prop
const updateSelectedOptions = (value: any | any[]) => {
  if (!listboxRef.value) return;

  const options = [...((listboxRef.value as any).options || [])];

  if (props.multiple && Array.isArray(value)) {
    options.forEach((option: any) => {
      option.selected = value.includes(option.value);
    });
  } else {
    options.forEach((option: any) => {
      option.selected = option.value === value;
    });
  }
};

// Handle option click events
const handleOptionClick = () => {
  if (!listboxRef.value) return;

  const options = [...((listboxRef.value as any).options || [])];

  if (props.multiple) {
    const selectedValues = options
      .filter((option: any) => option.selected)
      .map((option: any) => option.value);

    emit('update:value', selectedValues);
    emit('change', selectedValues);
  } else {
    const selectedOption = options.find((option: any) => option.selected);
    const newValue = selectedOption ? selectedOption.value : null;

    emit('update:value', newValue);
    emit('change', newValue);
  }
};
</script>

<template>
  <fluent-listbox
    ref="listboxRef"
    :id="id"
    :multiple="multiple"
    :disabled="disabled"
  >
    <slot></slot>
  </fluent-listbox>
</template>
